package com.akk.module.hkpay.util;

import com.akk.PayConstants;
import com.akk.utils.Md5Utils;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.tomcat.util.security.MD5Encoder;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

public class HkUtils {

    public static String signatureStr(Map<String, String> map) {
        String str = "";
        for (String key : map.keySet()) {
            if (map.get(key) != null && map.get(key).length() > 0) {
                str += key + "=" + map.get(key) + "&";
            }
        }
        str += "key=" + PayConstants.HK_CARD_WALLET_KEY;
        return str;
    }

    public static String createSortUrl(String json,String [] nos) {
        StringBuilder sb = new StringBuilder();
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            Map maps = objectMapper.readValue(json, Map.class);
            Map<String, Object> appBody = (Map<String, Object>) maps.get("AppBody");
            Set<String> set = appBody.keySet();

            // 删除不参与签名校验的字段
            if (nos != null){
                for (String key:nos) {
                    appBody.remove(key);
                }
            }

            // 排序
            Set<String> sortSet = new TreeSet<String>();
            sortSet.addAll(set);

            // 删除sign
            sortSet.remove("sign");

            // 构造url
            Iterator<String> it = sortSet.iterator();
            while (it.hasNext()) {
                String key = it.next();
                Object value = appBody.get(key);
                sb.append("&").append(key).append("=").append(value);
            }
            sb.append("&key=");
        } catch (Exception e) {
            e.printStackTrace();
            sb.append("&");
        }
        return sb.substring(1);
    }

    /**
     * 对参数key进行排序(java.util.Arrays的排序方法)，然后使用指定密钥进行md5加签，忽略null值及空符串
     *
     * @param params
     * @param secretKey
     * @return
     */
    public static String sign(Map<String, String> params, String secretKey, String signKeyName) {
        // 对参数排序
        LinkedHashMap<String, String> sorts = new LinkedHashMap<String, String>();
        Set<String> keySet = params.keySet();
        String[] keys = new String[keySet.size()];
        keys = keySet.toArray(keys);
        Arrays.sort(keys);
        for (int i = 0; i < keys.length; i++) {
            String key = keys[i];
            sorts.put(key, params.get(key));
        }
        // 加签
        StringBuilder signKeys = new StringBuilder();
        for (Map.Entry<String, String> entry : sorts.entrySet()) {
            if (entry.getValue() == null || entry.getValue().isEmpty()) {
                continue;
            }
            signKeys.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
        }
        signKeys.append(signKeyName).append("=").append(secretKey);
        return md5UTF8Hex(signKeys.toString());
    }

    /**
     * 通常用的MD5加密：MD5加密字符串的UTF-8字节
     */
    public static String md5UTF8Hex(String str) {
        try {
            byte[] bs = str.getBytes("UTF-8");
            MessageDigest md = MessageDigest.getInstance("MD5");
            return byteToHex(md.digest(bs));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e); // 中文平台，都会支持GBK字符集
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);    // 因为JDK实现了MD5算法，所以该异常理论上不可能出现
        }
    }

    /**
     * 将byte[]转为16进制的字符串数组
     */
    public static String byteToHex(byte[] bs) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < bs.length; i++) {
            int c = bs[i];
            if (c < 0) {
                c += 256;
            }
            // 转16进制字符串
            String hex = Integer.toHexString(c);
            if (hex.length() == 1) {
                sb.append("0");
            }
            sb.append(hex);
        }
        return sb.toString();
    }

    /**
     * 将一个java对象换为json字符串
     */
    public static String toJson(Object object) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            return mapper.writeValueAsString(object);
        } catch (Exception e) {
            throw new RuntimeException("对象转json失败:" + e.getMessage(), e);
        }
    }

    /**
     * 将一个json字符串转换为java对象
     */
    public static <T> T parse(String json, Class<T> classs) {
        try {
            ObjectMapper mapper = new ObjectMapper();
            return mapper.readValue(json, classs);
        } catch (Exception e) {
            throw new RuntimeException("json转对象失败:" + e.getMessage(), e);
        }
    }

    public static String URLPost(String ur, String str) {
        try {
            URL url = new URL(ur);
            URLConnection rulConnection = null;
            rulConnection = url.openConnection();
            // urlConnection对象实际上是根据URL的请求协议(此处是http)生成的URLConnection类的子类HttpURLConnection,故此处最好将其转化为HttpURLConnection类型的对象,以便用到
            HttpURLConnection httpUrlConnection = (HttpURLConnection) rulConnection;
            // 设置是否向httpUrlConnection输出，因为这个是post请求，参数要放在http正文内，因此需要设为true,
            // 默认情况下是false;
            httpUrlConnection.setDoOutput(true);
            // 设置是否从httpUrlConnection读入，默认情况下是true;
            httpUrlConnection.setDoInput(true);
            // Post 请求不能使用缓存
            httpUrlConnection.setUseCaches(false);
            // 设定传送的内容类型是可序列化的java对象
            // (如果不设此项,在传送序列化对象时,当WEB服务默认的不是这种类型时可能抛java.io.EOFException)
            httpUrlConnection.setRequestProperty("Content-Type", "application/soap+xml; charset=UTF-8");
            // 设置连接主机超时（单位：毫秒） ,读取数据连接
            httpUrlConnection.setConnectTimeout(8000);
            httpUrlConnection.setReadTimeout(100000);
            // 设定请求的方法为"POST"，默认是GET
            httpUrlConnection.setRequestMethod("POST");
            BufferedWriter bout = new BufferedWriter(new OutputStreamWriter(httpUrlConnection.getOutputStream(), "UTF-8"));
            // 开始发送字符串
            // String s = new String(str.getBytes(),"UTF-8");
            String s = str;
            bout.write(s);
            // 刷新对象输出流，将任何字节都写入潜在的流中（些处为ObjectOutputStream）
            bout.flush();
            // 关闭流对象。此时，不能再向对象输出流写入任何数据，先前写入的数据存在于内存缓冲区中,
            // 在调用下边的getInputStream()函数时才把准备好的http请求正式发送到服务器
            bout.close();

            int response = httpUrlConnection.getResponseCode();
            System.out.println("代码：");
            System.out.println(response);
            StringBuffer result = new StringBuffer();
            // 返回200说明已经请求成功
            switch (response) {
                case 200:
                    InputStream inStrm = httpUrlConnection.getInputStream();
                    Reader reader = null;
                    BufferedReader bufferedReader = null;
                    reader = new InputStreamReader(inStrm, "UTF-8");
                    bufferedReader = new BufferedReader(reader);
                    String line = null;
                    while ((line = bufferedReader.readLine()) != null) {
                        result.append(line);
                    }
                    System.out.println("内容：");
                    System.out.println(result);
                    bufferedReader.close();
                    inStrm.close();
            }
            return result.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";

    }

}
